home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / OS / FWGraphx / Sources / SLRegion.cpp < prev    next >
Encoding:
Text File  |  1996-04-25  |  24.5 KB  |  865 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                SLRegion.cpp
  4. //    Release Version:    $ ODF 1 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWOS.hpp"
  11.  
  12. #ifndef SLREGION_H
  13. #include "SLRegion.h"
  14. #endif
  15.  
  16. #ifndef FWFXMATH_H
  17. #include "FWFxMath.h"
  18. #endif
  19.  
  20. #ifndef FWRECT_H
  21. #include "FWRect.h"
  22. #endif
  23.  
  24. #ifndef FWPOINT_H
  25. #include "FWPoint.h"
  26. #endif
  27.  
  28. #ifndef SLGRGLOB_H
  29. #include "SLGrGlob.h"
  30. #endif
  31.  
  32. #ifndef PRGRUTIL_H
  33. #include "PRGrUtil.h"
  34. #endif
  35.  
  36. #ifndef FWPRIDEB_H
  37. #include "FWPriDeb.h"
  38. #endif
  39.  
  40. #ifndef FWSTRMRW_H
  41. #include "FWStrmRW.h"
  42. #endif
  43.  
  44. #ifndef FWMEMHLP_H
  45. #include "FWMemHlp.h"
  46. #endif
  47.  
  48. #ifdef FW_BUILD_MAC
  49. #pragma segment FWGraphx_Region
  50. #endif
  51.  
  52. //========================================================================================
  53. //    Local helpers
  54. //========================================================================================
  55.  
  56. #ifdef FW_BUILD_MAC
  57. static GrafPtr        PrivMacOpenRegion();
  58. static ODRgnHandle    PrivMacCloseRegion(GrafPtr svPort);
  59. #endif
  60.  
  61. #ifdef FW_BUILD_WIN
  62. static void PrivWinInsetRegionRectangle(LPPOINT lppt, int dx, int dy, const POINT& ptCenter);
  63. static void PrivWinInsetRegionRectangle(LPRECT lpRect, int dx, int dy, const POINT& ptCenter);
  64. #endif
  65.  
  66. //========================================================================================
  67. //    Region functions
  68. //========================================================================================
  69.  
  70. //----------------------------------------------------------------------------------------
  71. //    FW_CreateRectRegion
  72. //----------------------------------------------------------------------------------------
  73.  
  74. ODRgnHandle SL_API    FW_CreateRectRegion(const FW_SRect& rect)
  75. {
  76.     // No try block necessary - Do not throw
  77.     FW_CPlatformRect plfmRect = rect;
  78.     
  79. #ifdef FW_BUILD_MAC
  80.     ODRgnHandle rgn = ::NewRgn();
  81.     ::RectRgn(rgn, &plfmRect);
  82.     return rgn;
  83. #endif
  84. #ifdef FW_BUILD_WIN
  85.     return ::CreateRectRgnIndirect(&plfmRect);
  86. #endif
  87. }
  88.  
  89. //----------------------------------------------------------------------------------------
  90. //    FW_CreateOvalRegion
  91. //----------------------------------------------------------------------------------------
  92.  
  93. ODRgnHandle SL_API    FW_CreateOvalRegion(const FW_SRect& rect)
  94. {
  95.     // No try block necessary - Do not throw
  96.     FW_CPlatformRect plfmRect(rect);
  97.  
  98. #ifdef FW_BUILD_MAC
  99.     GrafPtr svPort = PrivMacOpenRegion();
  100.     ::FrameOval(&plfmRect);
  101.     return PrivMacCloseRegion(svPort);
  102. #endif
  103.  
  104. #ifdef FW_BUILD_WIN
  105.     return ::CreateEllipticRgnIndirect(&plfmRect);
  106. #endif
  107. }
  108.  
  109. //----------------------------------------------------------------------------------------
  110. //    FW_CreateRoundRectRegion
  111. //----------------------------------------------------------------------------------------
  112.  
  113. ODRgnHandle SL_API    FW_CreateRoundRectRegion(const FW_SRect& rect, const FW_SPoint& ovalSize)
  114. {
  115.     // No try block necessary - Do not throw
  116.     FW_CPlatformRect plfmRect(rect);
  117.     FW_CPlatformPoint plfmPoint(ovalSize);
  118.  
  119. #ifdef FW_BUILD_MAC
  120.     GrafPtr svPort = PrivMacOpenRegion();
  121.     ::FrameRoundRect(&plfmRect, plfmPoint.X(), plfmPoint.Y());
  122.     return ::PrivMacCloseRegion(svPort);
  123. #endif
  124. #ifdef FW_BUILD_WIN
  125.     return ::CreateRoundRectRgn(plfmRect.left, plfmRect.top, 
  126.                                 plfmRect.right, plfmRect.bottom, 
  127.                                 plfmPoint.X(), plfmPoint.Y());
  128. #endif
  129. }
  130.  
  131. //----------------------------------------------------------------------------------------
  132. //    FW_CreateArcRegion
  133. //----------------------------------------------------------------------------------------
  134.  
  135. ODRgnHandle SL_API    FW_CreateArcRegion(const FW_SRect& rect, short startAngle, short arcAngle)
  136. {
  137.     // No try block necessary - Do not throw
  138.     FW_CPlatformRect plfmRect = rect;
  139.  
  140.     // Create an elliptic region
  141. #ifdef FW_BUILD_MAC
  142.     GrafPtr savePort = ::PrivMacOpenRegion();
  143.     ::FrameOval(&plfmRect);
  144.     ODRgnHandle hEllipticRgn = ::PrivMacCloseRegion(savePort);
  145. #endif
  146. #ifdef FW_BUILD_WIN
  147.     // Create an elliptic region
  148.     HRGN hEllipticRgn = ::CreateEllipticRgnIndirect(&plfmRect);
  149. #endif
  150.  
  151.     short angle0 = startAngle,
  152.           angle1 = startAngle + arcAngle * 1 / 4,
  153.           angle2 = startAngle + arcAngle * 2 / 4,
  154.           angle3 = startAngle + arcAngle * 3 / 4,
  155.           angle4 = startAngle + arcAngle;
  156.           
  157.     FW_PlatformCoordinate width  = plfmRect.right - plfmRect.left;
  158.     FW_PlatformCoordinate height = plfmRect.bottom - plfmRect.top;
  159.     FW_CPlatformRect polygonRect(plfmRect.left - width, plfmRect.top - height,
  160.                                  plfmRect.right + width, plfmRect.bottom + height);
  161.     
  162.     FW_CPlatformPoint pt[6];
  163.     
  164.     FW_PrivCalcArcPoints(polygonRect, angle0, pt[0]);
  165.     FW_PrivCalcArcPoints(polygonRect, angle1, pt[1]);
  166.     FW_PrivCalcArcPoints(polygonRect, angle2, pt[2]);
  167.     FW_PrivCalcArcPoints(polygonRect, angle3, pt[3]);
  168.     FW_PrivCalcArcPoints(polygonRect, angle4, pt[4]);
  169.     
  170.     pt[5].Set((plfmRect.left + plfmRect.right) / 2,
  171.               (plfmRect.top + plfmRect.bottom) / 2);
  172.  
  173.     // Create a polygon region
  174. #ifdef FW_BUILD_MAC
  175.      savePort = ::PrivMacOpenRegion();
  176.     
  177.     ::MoveTo(pt[0].h, pt[0].v);
  178.     for(short i = 1; i < 6; i ++)
  179.         ::LineTo(pt[i].h, pt[i].v);
  180.  
  181.     ODRgnHandle hPolygonRgn = ::PrivMacCloseRegion(savePort);
  182. #endif
  183. #ifdef FW_BUILD_WIN
  184.     ODRgnHandle hPolygonRgn = ::CreatePolygonRgn(pt, 6, WINDING);
  185. #endif
  186.  
  187.     // Intersect the regions
  188.     ODRgnHandle hArcRegion = ::FW_NewRegion();
  189.     
  190. #ifdef FW_BUILD_MAC
  191.     ::SectRgn(hEllipticRgn, hPolygonRgn, hArcRegion);
  192. #endif
  193. #ifdef FW_BUILD_WIN
  194.     ::CombineRgn(hArcRegion, hEllipticRgn, hPolygonRgn, RGN_AND);
  195. #endif
  196.  
  197.     // Clean up
  198.     ::FW_DisposeRegion(hEllipticRgn);
  199.     ::FW_DisposeRegion(hPolygonRgn);
  200.  
  201.     // Return the result
  202.     return hArcRegion;
  203. }
  204.  
  205. //----------------------------------------------------------------------------------------
  206. //    FW_CreatePolygonRegion
  207. //----------------------------------------------------------------------------------------
  208.  
  209. ODRgnHandle SL_API    FW_CreatePolygonRegion(unsigned long pointCount, const FW_SPoint* pointArray)
  210. {
  211.     // No try block necessary - Do not throw
  212. #ifdef FW_BUILD_MAC
  213.     GrafPtr savePort = ::PrivMacOpenRegion();
  214.     
  215.     FW_CPlatformPoint pt = pointArray[0];
  216.     ::MoveTo(pt.h, pt.v);
  217.     
  218.     for(unsigned long i = 1; i < pointCount; i ++)
  219.     {
  220.         pt = pointArray[i];
  221.         ::LineTo(pt.h, pt.v);
  222.     }
  223.  
  224.     return ::PrivMacCloseRegion(savePort);
  225. #endif
  226. #ifdef FW_BUILD_WIN
  227.     FW_CPlatformPoint* points = new FW_CPlatformPoint[pointCount];
  228.     
  229.     for(unsigned long i = 0; i < pointCount; i ++)
  230.         points[i] = pointArray[i];
  231.  
  232.     HRGN hRgn = ::CreatePolygonRgn(points, pointCount, ALTERNATE);
  233.     delete[] points;
  234.     
  235.     return hRgn;
  236. #endif
  237. }
  238.  
  239. //----------------------------------------------------------------------------------------
  240. //    FW_CreateLineRegion
  241. //----------------------------------------------------------------------------------------
  242.  
  243. ODRgnHandle SL_API    FW_CreateLineRegion(const FW_SPoint& startPt,
  244.                                              const FW_SPoint& endPt,
  245.                                              const FW_SPoint& lineThickness)
  246. {
  247.     // No try block necessary - Do not throw
  248.     ODRgnHandle rgn;
  249.     
  250.     FW_CPlatformPoint firstPoint(startPt);
  251.     FW_CPlatformPoint lastPoint(endPt);
  252.     FW_CPlatformPoint penSize(lineThickness);
  253.     
  254.     FW_CPlatformRect halfPen(-penSize.X() / 2, -penSize.Y() / 2, (penSize.X() + 1) / 2, (penSize.Y() + 1) / 2);
  255.  
  256.     FW_CPlatformRect rect(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top, firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  257.  
  258.     short regionCode = 0;
  259.     if (lastPoint.X() < rect.left)
  260.         regionCode = 0x0008;
  261.     else if (lastPoint.X() > rect.right)
  262.         regionCode = 0x0004;
  263.     
  264.     if (lastPoint.Y() < rect.top)
  265.         regionCode |= 0x0001;
  266.     else if (lastPoint.Y() > rect.bottom)
  267.         regionCode |= 0x0002;
  268.  
  269.     short nbPoint;
  270.     FW_CPlatformPoint pt[6];
  271.     
  272.     switch (regionCode)
  273.     {
  274.         case 0x0000:
  275.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  276.             pt[1].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  277.             nbPoint = 2;
  278.             break;
  279.         case 0x0004:
  280.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  281.             pt[1].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  282.             nbPoint = 2;
  283.             break;
  284.         case 0x0008:
  285.             pt[0].Set(lastPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  286.             pt[1].Set(firstPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  287.             nbPoint = 2;
  288.             break;
  289.         case 0x0002:
  290.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  291.             pt[1].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  292.             nbPoint = 2;
  293.             break;
  294.         case 0x0001:
  295.             pt[0].Set(firstPoint.X() + halfPen.left, lastPoint.Y() + halfPen.top);
  296.             pt[1].Set(lastPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  297.             nbPoint = 2;
  298.             break;
  299.         case 0x0005:
  300.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  301.             pt[1].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.bottom);
  302.             pt[2].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  303.             pt[3].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  304.             pt[4].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.top);
  305.             pt[5].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.top);
  306.             nbPoint = 6;
  307.             break;
  308.         case 0x0006:
  309.             pt[0].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.top);
  310.             pt[1].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  311.             pt[2].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.bottom);
  312.             pt[3].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.bottom);
  313.             pt[4].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  314.             pt[5].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.top);
  315.             nbPoint = 6;
  316.             break;
  317.         case 0x000A:
  318.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  319.             pt[1].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.top);
  320.             pt[2].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  321.             pt[3].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  322.             pt[4].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.bottom);
  323.             pt[5].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.top);
  324.             nbPoint = 6;
  325.             break;
  326.         case 0x0009:
  327.             pt[0].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.top);
  328.             pt[1].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  329.             pt[2].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.bottom);
  330.             pt[3].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.bottom);
  331.             pt[4].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.top);
  332.             pt[5].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.top);
  333.             nbPoint = 6;
  334.             break;
  335.     }
  336.     
  337. #ifdef FW_BUILD_WIN
  338.     if (nbPoint == 2)
  339.         rgn = ::CreateRectRgn(pt[0].x, pt[0].y, pt[1].x, pt[1].y);
  340.     else
  341.         rgn = ::CreatePolygonRgn(pt, nbPoint, WINDING);
  342. #endif        
  343.     
  344. #ifdef FW_BUILD_MAC
  345.     if (nbPoint == 2)
  346.     {
  347.         rgn = ::NewRgn();
  348.         FW_CPlatformRect rect(pt[0], pt[1]);
  349.         ::RectRgn(rgn, &rect);
  350.     }
  351.     else
  352.     {
  353.         GrafPtr svPort = ::PrivMacOpenRegion();
  354.         ::MoveTo(pt[0].h, pt[0].v);
  355.         ::LineTo(pt[1].h, pt[1].v);
  356.         ::LineTo(pt[2].h, pt[2].v);            
  357.         ::LineTo(pt[3].h, pt[3].v);
  358.         ::LineTo(pt[4].h, pt[4].v);            
  359.         ::LineTo(pt[5].h, pt[5].v);
  360.         ::LineTo(pt[0].h, pt[0].v);
  361.         rgn = ::PrivMacCloseRegion(svPort);
  362.     }
  363. #endif
  364.  
  365.     return rgn;
  366. }
  367.  
  368. //----------------------------------------------------------------------------------------
  369. //    FW_CopyRegion
  370. //----------------------------------------------------------------------------------------
  371.  
  372. ODRgnHandle SL_API    FW_CopyRegion(ODRgnHandle scrRgn)
  373. {
  374.     // No try block necessary - Do not throw
  375.     FW_ASSERT(scrRgn != NULL);
  376.     
  377. #ifdef FW_BUILD_MAC
  378.     ODRgnHandle newRgn = ::NewRgn();
  379.     ::CopyRgn(scrRgn, newRgn);
  380.     return newRgn;
  381. #endif
  382. #ifdef FW_BUILD_WIN
  383.     ODRgnHandle newRgn = ::CreateRectRgn(0,0,0,0);
  384.     ::CombineRgn(newRgn, scrRgn, NULL, RGN_COPY);
  385.     return newRgn;
  386. #endif
  387. }
  388.  
  389. //----------------------------------------------------------------------------------------
  390. //    FW_CopyRegionTo
  391. //----------------------------------------------------------------------------------------
  392.  
  393. void SL_API    FW_CopyRegionTo(ODRgnHandle scrRgn, ODRgnHandle dstRgn)
  394. {
  395.     // No try block necessary - Do not throw
  396.     FW_ASSERT(scrRgn != NULL);
  397.     FW_ASSERT(dstRgn != NULL);
  398.     
  399. #ifdef FW_BUILD_MAC
  400.     ::CopyRgn(scrRgn, dstRgn);
  401. #endif
  402. #ifdef FW_BUILD_WIN
  403.     ::CombineRgn(dstRgn, scrRgn, NULL, RGN_COPY);
  404. #endif
  405. }
  406.  
  407. //----------------------------------------------------------------------------------------
  408. //    FW_NewRegion
  409. //----------------------------------------------------------------------------------------
  410.  
  411. ODRgnHandle SL_API    FW_NewRegion()
  412. {    
  413.     // No try block necessary - Do not throw
  414. #ifdef FW_BUILD_MAC
  415.     return ::NewRgn();
  416. #endif
  417. #ifdef FW_BUILD_WIN
  418.     return    ::CreateRectRgn(0,0,0,0);
  419. #endif
  420. }
  421.  
  422. //----------------------------------------------------------------------------------------
  423. //    FW_DisposeRegion
  424. //----------------------------------------------------------------------------------------
  425.  
  426. void SL_API    FW_DisposeRegion(ODRgnHandle rgn)
  427. {
  428.     // No try block necessary - Do not throw
  429.     FW_ASSERT(rgn != 0);
  430.     
  431. #ifdef FW_BUILD_MAC
  432.     ::DisposeRgn(rgn);
  433. #endif
  434. #ifdef FW_BUILD_WIN
  435.     ::DeleteObject(rgn);
  436. #endif
  437. }
  438.  
  439. //----------------------------------------------------------------------------------------
  440. //    FW_OutlineRegion
  441. //----------------------------------------------------------------------------------------
  442.  
  443. void SL_API    FW_OutlineRegion(ODRgnHandle rgn, FW_Fixed outlineSize)
  444. {
  445.     ODRgnHandle tempRgn = ::FW_CopyRegion(rgn);
  446.     
  447.     if (outlineSize <= FW_kFixed0)
  448.         outlineSize = FW_kFixedPos1;
  449.     
  450.     ::FW_InsetRegion(tempRgn, outlineSize, outlineSize);
  451.     
  452. #ifdef FW_BUILD_MAC
  453.     ::DiffRgn(rgn, tempRgn, rgn);
  454. #endif
  455. #ifdef FW_BUILD_WIN
  456.     ::CombineRgn(rgn, rgn, tempRgn, RGN_DIFF);
  457. #endif
  458.  
  459.     ::FW_DisposeRegion(tempRgn);
  460. }
  461.  
  462. //----------------------------------------------------------------------------------------
  463. //    FW_InsetRegion
  464. //----------------------------------------------------------------------------------------
  465.  
  466. void SL_API    FW_InsetRegion(ODRgnHandle rgn, FW_Fixed x, FW_Fixed y)
  467. {
  468.     // No try block necessary - Do not throw
  469. #ifdef FW_BUILD_MAC
  470.     ::InsetRgn(rgn, FW_FixedToInt(x), FW_FixedToInt(y));
  471. #endif
  472. #ifdef FW_BUILD_WIN
  473.     int dx = FW_FixedToInt(x);
  474.     int dy = FW_FixedToInt(y);
  475.     
  476.     if (dx == 0 && dy == 0)
  477.         return;
  478.  
  479.     // Note: This code relies on partially documented Windows GDI data structures!
  480.  
  481.     // Get the current region data
  482.     long size = ::GetRegionData(rgn, 0, NULL);
  483.     
  484.     FW_CAcquireTemporaryMemory tempMem(size);
  485.     LPRGNDATA rgnData = (LPRGNDATA) tempMem.GetPointer();
  486.     ::GetRegionData(rgn, size, rgnData);
  487.     
  488.     // Massage the region data
  489.     if(rgnData->rdh.iType == RDH_RECTANGLES)
  490.     {
  491.         POINT ptCenter;
  492.         ptCenter.x = (rgnData->rdh.rcBound.left + rgnData->rdh.rcBound.right) / 2;
  493.         ptCenter.y = (rgnData->rdh.rcBound.top  + rgnData->rdh.rcBound.bottom) / 2;
  494.         
  495.         LPRECT lpRect = (LPRECT) rgnData->Buffer;
  496.  
  497.         for(unsigned long i = 0; i < rgnData->rdh.nCount; ++ i, ++ lpRect)
  498.             ::PrivWinInsetRegionRectangle(lpRect, dx, dy, ptCenter);
  499.     }
  500.  
  501.     // Create a new region and replace the one passed in    
  502.     HRGN hNewRgn = ::ExtCreateRegion(NULL, size, rgnData);
  503.     if(hNewRgn == NULL)
  504.         FW_Failure(FW_xMemoryExhausted);
  505.  
  506.     ::FW_CopyRegionTo(hNewRgn, rgn);
  507.     ::FW_DisposeRegion(hNewRgn);
  508. #endif
  509. }
  510.  
  511. //----------------------------------------------------------------------------------------
  512. //    FW_MapRegion
  513. //----------------------------------------------------------------------------------------
  514.  
  515. void SL_API    FW_MapRegion(ODRgnHandle rgn, const FW_SRect& srcRect, const FW_SRect& dstRect)
  516. {
  517.     // No try block necessary - Do not throw
  518.     FW_CPlatformRect plfmSrc(srcRect);
  519.     FW_CPlatformRect plfmDst(dstRect);
  520.     
  521. #ifdef FW_BUILD_MAC
  522.     ::MapRgn(rgn, &plfmSrc, &plfmDst);
  523. #endif
  524. #ifdef FW_BUILD_WIN
  525.     // Get the current region data
  526.     long size = ::GetRegionData(rgn, 0, NULL);
  527.     
  528.     FW_CAcquireTemporaryMemory tempMem(size);
  529.     LPRGNDATA rgnData = (LPRGNDATA) tempMem.GetPointer();
  530.     ::GetRegionData(rgn, size, rgnData);
  531.  
  532.     // Figure out the desired transform
  533.     XFORM xform;
  534.     xform.eM11 = (float) FW_FixedToDouble((dstRect.right - dstRect.left) / (srcRect.right - srcRect.left));
  535.     xform.eM12 = 0.0f;
  536.     xform.eM21 = 0.0f;
  537.     xform.eM22 = (float) FW_FixedToDouble((dstRect.bottom - dstRect.top) / (srcRect.bottom - srcRect.top));
  538.     xform.eDx  = (float) FW_FixedToDouble(dstRect.left - srcRect.left);
  539.     xform.eDy  = (float) FW_FixedToDouble(dstRect.top  - srcRect.top);
  540.  
  541.     // Create a new region and replace the one passed in    
  542.     HRGN hNewRgn = ::ExtCreateRegion(&xform, size, rgnData);
  543.     if(hNewRgn == NULL)
  544.         FW_Failure(FW_xMemoryExhausted);
  545.  
  546.     ::FW_CopyRegionTo(hNewRgn, rgn);
  547.     ::FW_DisposeRegion(hNewRgn);
  548. #endif
  549. }
  550.  
  551. //----------------------------------------------------------------------------------------
  552. //    FW_EmptyRegion
  553. //----------------------------------------------------------------------------------------
  554.  
  555. void SL_API    FW_EmptyRegion(ODRgnHandle rgn)
  556. {
  557.     // No try block necessary - Do not throw
  558. #ifdef FW_BUILD_MAC
  559.     ::SetEmptyRgn(rgn);
  560. #endif
  561. #ifdef FW_BUILD_WIN
  562.     ::SetRectRgn(rgn, 0, 0, 0, 0);
  563. #endif
  564. }
  565.  
  566. //----------------------------------------------------------------------------------------
  567. //    FW_OffsetRegion
  568. //----------------------------------------------------------------------------------------
  569.  
  570. void SL_API    FW_OffsetRegion(ODRgnHandle rgn, FW_Fixed x, FW_Fixed y)
  571. {
  572.     ::OffsetRgn(rgn, FW_FixedToInt(x), FW_FixedToInt(y));
  573. }
  574.  
  575. //----------------------------------------------------------------------------------------
  576. //    FW_GetRegionBoundingBox
  577. //----------------------------------------------------------------------------------------
  578.  
  579. void SL_API    FW_GetRegionBoundingBox(ODRgnHandle rgn, FW_SRect& rect)
  580. {
  581.     // No try block necessary - Do not throw
  582. #ifdef FW_BUILD_MAC
  583.     rect = FW_CRect((*rgn)->rgnBBox);
  584. #endif
  585. #ifdef FW_BUILD_WIN
  586.     FW_CPlatformRect plfmRect;
  587.     ::GetRgnBox(rgn, &plfmRect);
  588.     rect = FW_CRect(plfmRect);
  589. #endif
  590. }
  591.  
  592. //----------------------------------------------------------------------------------------
  593. //    FW_PointInRegion
  594. //----------------------------------------------------------------------------------------
  595.  
  596. FW_Boolean SL_API    FW_PointInRegion(ODRgnHandle rgn, const FW_SPoint& point)
  597. {
  598.     // No try block necessary - Do not throw
  599.     FW_CPlatformPoint plfmPt = point;
  600. #ifdef FW_BUILD_MAC
  601.     return ::PtInRgn(plfmPt, rgn);
  602. #endif
  603. #ifdef FW_BUILD_WIN
  604.     return ::PtInRegion(rgn, plfmPt.X(), plfmPt.Y());
  605. #endif
  606. }
  607.  
  608. //----------------------------------------------------------------------------------------
  609. //    FW_RectInRegion
  610. //----------------------------------------------------------------------------------------
  611.  
  612. FW_Boolean SL_API    FW_RectInRegion(ODRgnHandle rgn, const FW_SRect& rect)
  613. {
  614.     // No try block necessary - Do not throw
  615.     FW_CPlatformRect plfmRect = rect;
  616. #ifdef FW_BUILD_MAC
  617.     return ::RectInRgn(&plfmRect, rgn);
  618. #endif
  619. #ifdef FW_BUILD_WIN
  620.     return ::RectInRegion(rgn, &plfmRect);
  621. #endif
  622. }
  623.  
  624. //----------------------------------------------------------------------------------------
  625. //    FW_IsEmptyRegion
  626. //----------------------------------------------------------------------------------------
  627.  
  628. FW_Boolean SL_API    FW_IsEmptyRegion(ODRgnHandle rgn)
  629. {
  630.     // No try block necessary - Do not throw
  631. #ifdef FW_BUILD_MAC
  632.     return ::EmptyRgn(rgn);
  633. #endif
  634. #ifdef FW_BUILD_WIN
  635.     return ::CombineRgn(rgn, rgn, rgn, RGN_AND) == NULLREGION;
  636. #endif
  637. }
  638.  
  639. #ifdef FW_BUILD_MAC
  640. //----------------------------------------------------------------------------------------
  641. //    PrivMacOpenRegion
  642. //----------------------------------------------------------------------------------------
  643.  
  644. static GrafPtr PrivMacOpenRegion()
  645. {
  646.     GrafPtr svPort;
  647.     ::GetPort(&svPort);
  648.     ::SetPort(FW_gScratchPort);
  649.     ::OpenRgn();
  650.     return svPort;
  651. }
  652. #endif
  653.  
  654. #ifdef FW_BUILD_MAC
  655. //----------------------------------------------------------------------------------------
  656. //    PrivMacCloseRegion
  657. //----------------------------------------------------------------------------------------
  658.  
  659. ODRgnHandle PrivMacCloseRegion(GrafPtr svPort)
  660. {
  661.     ODRgnHandle hRgn = ::NewRgn();
  662.     ::CloseRgn(hRgn);
  663.     ::SetPort(svPort);
  664.     return hRgn;
  665. }
  666. #endif
  667.  
  668. #ifdef FW_BUILD_WIN
  669.  
  670. //----------------------------------------------------------------------------------------
  671. //    PrivWinInsetRegionPoint
  672. //----------------------------------------------------------------------------------------
  673.  
  674. static void PrivWinInsetRegionRectangle(LPPOINT lppt, int dx, int dy, const POINT& ptCenter)
  675. {
  676.     if (lppt->x < ptCenter.x)
  677.     {
  678.         if ((lppt->x += dx) > ptCenter.x)
  679.             lppt->x = ptCenter.x;
  680.     }
  681.     else
  682.     {
  683.         if ((lppt->x -= dx) < ptCenter.x)
  684.             lppt->x = ptCenter.x;
  685.     }
  686.  
  687.     if (lppt->y < ptCenter.y)
  688.     {
  689.         if((lppt->y += dy) > ptCenter.y)
  690.             lppt->y = ptCenter.y;
  691.     }
  692.     else
  693.     {
  694.         if ((lppt->y -= dy) < ptCenter.y)
  695.             lppt->y = ptCenter.y;
  696.     }
  697. }
  698.  
  699. //----------------------------------------------------------------------------------------
  700. //    PrivWinInsetRegionRectangle
  701. //----------------------------------------------------------------------------------------
  702.  
  703. static void PrivWinInsetRegionRectangle(LPRECT lpRect, int dx, int dy, const POINT& ptCenter)
  704. {
  705.     PrivWinInsetRegionRectangle(((LPPOINT) lpRect) + 0, dx, dy, ptCenter);
  706.     PrivWinInsetRegionRectangle(((LPPOINT) lpRect) + 1, dx, dy, ptCenter);
  707. }
  708.  
  709. #endif
  710.  
  711. //----------------------------------------------------------------------------------------
  712. //    FW_WriteRegion
  713. //----------------------------------------------------------------------------------------
  714.  
  715. void SL_API FW_WriteRegion(ODRgnHandle rgnHandle, FW_HWritableStream hStream, FW_PlatformError* error)
  716. {
  717.     FW_ERR_TRY
  718.     {
  719.         FW_CWritableStream stream(hStream);
  720.     
  721. #ifdef FW_BUILD_WIN
  722.         long size = ::GetRegionData(rgnHandle, 0, NULL);
  723.         
  724.         FW_CAcquireTemporaryMemory tempMem(size);
  725.         LPRGNDATA rgnData = (LPRGNDATA) tempMem.GetPointer();
  726.         ::GetRegionData(rgnHandle, size, rgnData);
  727.         
  728.         stream << size;
  729.         stream.Write(rgnData, size);
  730. #endif
  731. #ifdef FW_BUILD_MAC
  732.         short size = (*rgnHandle)->rgnSize;
  733.         
  734.         FW_CAcquireLockedSystemHandle memHandle((FW_PlatformHandle)rgnHandle);
  735.         void* rgnData = memHandle.GetPointer();
  736.         
  737.         stream << size;
  738.         stream.Write(rgnData, size);
  739. #endif
  740.     }
  741.     FW_ERR_CATCH
  742. }
  743.  
  744. //----------------------------------------------------------------------------------------
  745. //    FW_ReadRegion
  746. //----------------------------------------------------------------------------------------
  747.  
  748. ODRgnHandle SL_API FW_ReadRegion(FW_HReadableStream hStream, FW_PlatformError* error)
  749. {
  750.     FW_ERR_TRY
  751.     {
  752.         FW_CReadableStream stream(hStream);
  753.     
  754. #ifdef FW_BUILD_WIN
  755.         long size;
  756.         stream >> size;
  757.         
  758.         FW_CAcquireTemporaryMemory tempMem(size);
  759.         LPRGNDATA rgnData = (LPRGNDATA) tempMem.GetPointer();
  760.         stream.Read(rgnData, size);
  761.     
  762.         return ::ExtCreateRegion(NULL, size, rgnData);
  763. #endif
  764. #ifdef FW_BUILD_MAC
  765.         short size;
  766.         stream >> size;
  767.         
  768.         FW_CAcquireTemporarySystemHandle memHandle(size);
  769.         void* rgnData = memHandle.GetPointer();
  770.         
  771.         stream.Read(rgnData, size);
  772.     
  773.         memHandle.Orphan();
  774.         return (ODRgnHandle) memHandle.GetPlatformHandle();
  775. #endif
  776.     }
  777.     FW_ERR_CATCH
  778.     return NULL;
  779. }
  780.  
  781. //----------------------------------------------------------------------------------------
  782. //    FW_UnionRegion
  783. //----------------------------------------------------------------------------------------
  784.  
  785. ODRgnHandle SL_API FW_UnionRegion(ODRgnHandle rgn1, ODRgnHandle rgn2)
  786. {
  787.     // No try block necessary - Do not throw
  788.     ODRgnHandle dstRgn = ::FW_NewRegion();
  789.     if (dstRgn == NULL)
  790.         return NULL;
  791.     
  792. #ifdef FW_BUILD_MAC
  793.     ::UnionRgn(rgn1, rgn2, dstRgn);
  794. #endif
  795. #ifdef FW_BUILD_WIN
  796.     ::CombineRgn(dstRgn, rgn1, rgn2, RGN_OR);
  797. #endif
  798.  
  799.     return dstRgn;
  800. }
  801.  
  802. //----------------------------------------------------------------------------------------
  803. //    FW_XorRegion
  804. //----------------------------------------------------------------------------------------
  805.  
  806. ODRgnHandle SL_API FW_XorRegion(ODRgnHandle rgn1, ODRgnHandle rgn2)
  807. {
  808.     // No try block necessary - Do not throw
  809.     ODRgnHandle dstRgn = ::FW_NewRegion();
  810.     if (dstRgn == NULL)
  811.         return NULL;
  812.         
  813. #ifdef FW_BUILD_MAC
  814.     ::XorRgn(rgn1, rgn2, dstRgn);
  815. #endif
  816. #ifdef FW_BUILD_WIN
  817.     ::CombineRgn(dstRgn, rgn1, rgn2, RGN_XOR);
  818. #endif
  819.  
  820.     return dstRgn;
  821. }
  822.  
  823. //----------------------------------------------------------------------------------------
  824. //    FW_SubtractRegion
  825. //----------------------------------------------------------------------------------------
  826.  
  827. ODRgnHandle SL_API FW_SubtractRegion(ODRgnHandle rgn1, ODRgnHandle rgn2)
  828. {
  829.     // No try block necessary - Do not throw
  830.     ODRgnHandle dstRgn = ::FW_NewRegion();
  831.     if (dstRgn == NULL)
  832.         return NULL;
  833.     
  834. #ifdef FW_BUILD_MAC
  835.     ::DiffRgn(rgn1, rgn2, dstRgn);
  836. #endif
  837. #ifdef FW_BUILD_WIN
  838.     ::CombineRgn(dstRgn, rgn1, rgn2, RGN_DIFF);
  839. #endif
  840.  
  841.     return dstRgn;
  842. }
  843.  
  844. //----------------------------------------------------------------------------------------
  845. //    FW_IntersectRegion
  846. //----------------------------------------------------------------------------------------
  847.  
  848. ODRgnHandle SL_API FW_IntersectRegion(ODRgnHandle rgn1, ODRgnHandle rgn2)
  849. {
  850.     // No try block necessary - Do not throw
  851.     ODRgnHandle dstRgn = ::FW_NewRegion();
  852.     if (dstRgn == NULL)
  853.         return NULL;
  854.     
  855. #ifdef FW_BUILD_MAC
  856.     ::SectRgn(rgn1, rgn2, dstRgn);
  857. #endif
  858. #ifdef FW_BUILD_WIN
  859.     ::CombineRgn(dstRgn, rgn1, rgn2, RGN_AND);
  860. #endif
  861.  
  862.     return dstRgn;
  863. }
  864.  
  865.